package com.fmc123.base.pesistence;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.fmc123.base.utils.Reflections;
import com.fmc123.base.utils.SqlHelper;
import com.fmc123.base.utils.StringUtils;



/**
 *
* @ClassName: HibernateBaseDao
* @Description: Hibernate DAO基类，提供对数据库操作的基础功能 
* @author fmc
* @date 2015年9月13日上午9:24:34
* 
* @param <T>
 */
@Repository
public  class  HibernateBaseDao<T,PK extends Serializable> {
	
	/**
	 * 日志对象
	 */
	protected Logger logger = LoggerFactory.getLogger(getClass());
	
	
	@Autowired
	private SessionFactory sessionFactory;
	
	/**
	 * 实体类类型(由构造方法自动赋值)
	 */
	private Class<?> entityClass;
	
	/**
	 * 构造方法，根据实例类自动获取实体类类型
	 */
	public HibernateBaseDao() {
		entityClass = Reflections.getClassGenricType(getClass());
	}
	
	/**
     * 用于用于省略Dao层, 在Service层直接使用通用SimpleHibernateDao的构造函数.
     * 在构造函数中定义对象类型Class.
     * eg.
     * SimpleHibernateDao<User, Long> userDao = new SimpleHibernateDao<User, Long>(sessionFactory, User.class);
     */
	public HibernateBaseDao(SessionFactory sessionFactory, Class<T> entityClass) {
      this.sessionFactory=sessionFactory;
      this.entityClass=entityClass;
    }

  /**
	 * 获取 Session
	 */
	public Session getSession(){  
	  return sessionFactory.getCurrentSession();
	}
	
	/**
	 * 强制与数据库同步
	 */
	public void flush(){
		getSession().flush();
	}

	/**
	 * 清除缓存数据
	 */
	public void clear(){ 
		getSession().clear();
	}
	
	/**
	 * 根据id获取实体
	 * @param entityClazz
	 * @param id
	 * @return 实体对象
	 */
	@SuppressWarnings("unchecked")
	public  T get(Class<T> entityClazz,PK id){
		return (T) getSession().get(entityClazz, id);
	}
	
  @SuppressWarnings("unchecked")
  public List<T> getAll(){
	  Query query=getSession().createQuery("from "+entityClass.getSimpleName()+
	    " where "+BaseEntity.DEL_FLAG_FIELD+" = "+BaseEntity.DEL_FLAG_NORMAL);
	  return (List<T>)query.list();
	}

    /**
     * hql分页查询
     * @param page
     * @param qlString
     * @param parameter
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public Page<T> find(Page<T> page,String hqlString, Parameter parameters){
      //查询总数
      String countHql="select count("+BaseEntity.ID+") "+SqlHelper.removeSelect(hqlString);
      Query query=getSession().createQuery(countHql);
      setParameters(query, parameters);
      List list=query.list();
      if(list.size()>0){
        page.setCount(Long.valueOf(list.get(0).toString()));
      }else{
        page.setCount(list.size());
      }
      if(page.getCount()<1){
        return page;
      }
      //设置排序
      if(StringUtils.isPresent(page.getOrderBy())){
        hqlString+=" order by ";
        hqlString+=page.getOrderBy();
        if(StringUtils.isNotBlank(hqlString)){
          hqlString+=" "+page.getOrderDirection();
        }
      }
      //分页查询
      query=getSession().createQuery(hqlString);
      setParameters(query, parameters);
      query.setFirstResult(page.getFirstResult());
      query.setMaxResults(page.getMaxResults());
      page.setList(query.list());
      return page;
    }
    
    /**
     * 分页查询
     * @param page 分页对象
     * @param entity 包含查询参数的实体类对象
     * @return
     */
    public Page<T> searchEntity(Page<T> page,T entity){
      StringBuffer hqlString =new StringBuffer("from "+entity.getClass().getSimpleName()+" where ");
      String where=SqlHelper.setParameters(entity);
      if(where.length()>0){
          hqlString.append(where).append(" and ");
      }
      try {
        hqlString.append(BaseEntity.class.newInstance().getQueryForDelFlag());
      } catch (InstantiationException | IllegalAccessException e) {
        e.printStackTrace();
      }
      return find(page, hqlString.toString(), null);
    }
  
	/**
	 * 根据id获取实体
	 * @param id
	 * @return 实体对象
	 */
	@SuppressWarnings("unchecked")
	public  T get(PK id){
		return (T) getSession().get(entityClass, id);
	}
	
	/**
	 * 保存实体，返回生成的实体id
	 * @param entity
	 * @return 实体id
	 */
	public Serializable save(T entity){
		return getSession().save(entity);
		
	}
	
	/**
	 * 更新实体类
	 * @param entity
	 */
	public void update(T entity){
		getSession().saveOrUpdate(entity);
	}
	
	/**
	 * 更新多个实体类
	 * @param entities
	 */
	public void udateAll(Collection<? extends T> entities){
		for(T entity:entities){
			update(entity);
		}
	}
	
	/**
	 * 删除实体类
	 * @param entity
	 */
	public void delete(T entity){
		getSession().delete(entity);
	}
	
	/**
	 * 删除多个实体类
	 * @param entities
	 */
	public void deleteAll(Collection<? extends T> entities){
		for(T entity:entities){
			delete(entity);
		}
	}
	
	/**
	 * 根据id删除实体
	 * @param id
	 */
	public void deleteById(PK id){
	  delete(get(id));
	}
	
	/**
	 * 设置hql参数
	 * @param query
	 * @param parameters
	 */
	public void setParameters(Query query,Parameter parameters){
	  if(null!=parameters){
	    Set<String> keySet=parameters.keySet();
	    for(String key:keySet){
	      Object value=parameters.get(key);
	      if(value instanceof Collection<?>){
	        query.setParameterList(key, (Collection<?>)value);
	      }else if(value instanceof Object[]){
	        query.setParameterList(key, (Object[])value);
	      }else{
	        query.setParameter(key, value);
	      }
	    }
	  }
	}
}
